package com.oktest.measure.media.video

/**
 * @Author hhh
 * @Date 2020/10/25
 */
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Color
import android.media.ThumbnailUtils
import android.provider.MediaStore
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.View.OnTouchListener
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.widget.FrameLayout
import android.widget.ImageView
import com.daasuu.camerarecorder.CameraRecordListener
import com.daasuu.camerarecorder.CameraRecorder
import com.daasuu.camerarecorder.CameraRecorderBuilder
import com.daasuu.camerarecorder.LensFacing
import com.oktest.measure.R
import com.oktest.measure.media.image.SampleGLView
import kotlinx.android.synthetic.main.recorde_video_layout.view.*
import kotlinx.coroutines.*
import java.io.File
import kotlin.coroutines.CoroutineContext
import kotlin.math.abs

class CameraSurfaceView(context: Context, attrs: AttributeSet?, defStyleAttr: Int)
    : FrameLayout(context, attrs, defStyleAttr), CoroutineScope{

    companion object{
        private const val RECORD_TIME_MAX = 10.0// 录制最长时间
        private const val RECORD_TIME_MIN = 2.0 // 录制最小时间
        private const val OFFSET_PRESS = 40.0f // 按住拍偏移距离
    }

    constructor(context: Context):this(context, null, 0)
    constructor(context: Context, attrs: AttributeSet?):this(context, attrs, 0)
    private val job = Job()
    private val recordingLayout = View.inflate(context, R.layout.recorde_video_layout, this)
    private lateinit var glView: SampleGLView
    private lateinit var ivFocus: ImageView
    private lateinit var cameraRecorder: CameraRecorder
    private val videoWidth = 720
    private val videoHeight = 1280
    private val cameraWidth = 1280
    private val cameraHeight = 720
    private var lensFacing = LensFacing.BACK
    private var focusWidth = 128 / 2
    // 录制
    private var startY: Float = 0f
    private var isRecording = false
    private var isRecordingCancel = false
    private var fileName = ""
    private var recordTime:Double = 0.0 // 记录时间
    private var countJob:Job? = null
    private var currentFile :File? = null
    private var currentBitmap: Bitmap? = null

    private val recordingListener:CameraRecordListener = object :CameraRecordListener{
        override fun onGetFlashSupport(flashSupport: Boolean) {
        }

        override fun onRecordComplete() {
            log("onRecordComplete")
            initVideoView()
        }

        override fun onRecordStart() {
        }

        override fun onError(exception: Exception?) {
            log("onError ${exception?.message}")
        }

        override fun onCameraThreadFinish() {
            log("onCameraThreadFinish")
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    private val btnRecordingListener = OnTouchListener { v, event ->
        when (event?.action) {
            MotionEvent.ACTION_DOWN -> {
                startY = event.y
                startAnim()
                changeState(TipState.CANCEL)
            }
            MotionEvent.ACTION_MOVE -> {
                // 判断是否超过10秒，超过保留
                if (recordTime > RECORD_TIME_MAX) {
                    stopRecording()
                    normalConfirm()
                }
                val offset = event.y - startY
                if (abs(offset) > OFFSET_PRESS) {
                    isRecordingCancel = true
                    changeState(TipState.RELEASE)
                } else {
                    isRecordingCancel = false
                    changeState(TipState.CANCEL)
                }
            }
            MotionEvent.ACTION_UP -> {
                log("started = ${cameraRecorder.isStarted},time = $recordTime")
                stopRecording()
                if (isRecordingCancel) {
                    hideTip()
                    deleteFile()
                    // 判断完取消就结束
                    return@OnTouchListener super.onTouchEvent(event)
                }
                if (recordTime < RECORD_TIME_MIN) {
                    shortCancelRecording()
                    return@OnTouchListener super.onTouchEvent(event)
                }
                normalConfirm()
            }
        }
        return@OnTouchListener super.onTouchEvent(event)
    }

    private fun normalConfirm() {
        btnRecord.visibility = View.GONE
        confirmLayout.visibility = View.VISIBLE
    }

    private fun startRecording() {
        currentFile = File(context.filesDir, "${System.currentTimeMillis()}-abc.mp4")
        log("create file ${currentFile?.absolutePath}")
        cameraRecorder.start(currentFile?.absolutePath)
        isRecording = true
        isRecordingCancel = false
        countJob = count()
    }

    private fun startAnim() {
        btnRecord.startRecordingAnim()
        progressView.startAnimation()
    }

    private fun changeState(state: TipState) {
        recordingLayout.tvRecordingTip.apply {
            setTextColor(Color.WHITE)
            text = state.tip
            visibility = View.VISIBLE
            setBackgroundColor(state.background)
        }
    }

    private fun count() = launch(Dispatchers.IO){
        recordTime = 0.0
        while (isRecording) {
            delay(100)
            recordTime += 0.1
        }
    }

    private fun stopRecording() {
        recordingLayout.apply {
            btnRecord.stopRecordingAnim()
            progressView.stopAnimation()
            tvRecordingTip.visibility = View.GONE
        }
        countJob?.cancel()
        cameraRecorder.stop()
        isRecording = false
    }

    private fun shortCancelRecording() {
        log("shortCancelRecording")
        changeState(TipState.SHORT)
        // 删除
        deleteFile()
        hideTip()
    }

    private fun deleteFile() {
        if (currentFile?.exists() == true) {
            val delete = currentFile?.delete()
            log("delete = $delete")
            recordTime = 0.0
        }
    }

    private fun hideTip()  = launch{
        delay(1000)
        recordingLayout.tvRecordingTip.visibility = View.GONE
    }
    init {
        setUpSurfaceView()
        recordingLayout.btnRecord.apply {
            setOnTouchListener(btnRecordingListener)
            setOnLongClickListener {
                startRecording()
                return@setOnLongClickListener true
            }
        }
        ivConfirm.setOnClickListener {
            val videoItem = VideoItem(currentFile?.absolutePath!!)
            videoItem.bitmap = currentBitmap
            confirmBlock(videoItem)
        }
        ivCancel.setOnClickListener {
            confirmLayout.visibility = View.GONE
            btnRecord.visibility = View.VISIBLE
            deleteFile()
        }
        ivPlay.setOnClickListener {
            val intent = Intent(context,VideoPlayActivity::class.java)
            intent.putExtra(VideoPlayActivity.FILE_PATH,currentFile?.absolutePath)
            context.startActivity(intent)
        }
    }

    private fun setUpSurfaceView() {
        glView = SampleGLView(context)
        ivFocus = createFocusView()
        recordingLayout.frameLayout.apply {
            removeAllViews()
            addView(glView)
            addView(ivFocus)
        }
        cameraRecorder = CameraRecorderBuilder(context as Activity, glView)
                .cameraRecordListener(recordingListener)
                .videoSize(videoWidth, videoHeight)
                .cameraSize(cameraWidth, cameraHeight)
                .lensFacing(lensFacing)
                .build()
        // 对焦
        glView.setTouchListener { event, width, height ->
            cameraRecorder.changeManualFocusPoint(event.x, event.y, width, height)
            val layoutParams = ivFocus.layoutParams as LayoutParams
            layoutParams.leftMargin = event.x.toInt() - focusWidth
            layoutParams.topMargin = event.y.toInt() - focusWidth
            ivFocus.layoutParams = layoutParams
            val loadAnimation = AnimationUtils.loadAnimation(context, R.anim.record_focus)
            loadAnimation.setAnimationListener(object : Animation.AnimationListener {
                override fun onAnimationStart(animation: Animation?) {
                    ivFocus.visibility = View.VISIBLE
                }

                override fun onAnimationEnd(animation: Animation?) {
                    ivFocus.visibility = View.GONE
                }

                override fun onAnimationRepeat(animation: Animation?) {

                }

            })
            ivFocus.startAnimation(loadAnimation)
        }
    }

    private fun initVideoView() = launch {
        delay(1000)
        currentBitmap = ThumbnailUtils.createVideoThumbnail(currentFile?.absolutePath!!,
                MediaStore.Video.Thumbnails.MINI_KIND)
        ivPlay.setImageBitmap(currentBitmap)
    }

    private fun createFocusView(): ImageView {
        return ImageView(context).also {
            val params = LayoutParams(focusWidth * 2,focusWidth * 2)
            it.setImageResource(R.mipmap.ms_video_focus_icon)
            it.layoutParams = params
            it.visibility = View.GONE
        }
    }

    override val coroutineContext: CoroutineContext
        get() = job + Dispatchers.Main


    fun onResume() {

    }

    fun onStop() {
        glView.onPause()
        cameraRecorder.stop()
        cameraRecorder.release()
    }

    fun onDestroy() {
        job.cancel()
    }

    private fun log(message: String) {
        Log.i("surfaceView","-> $message")
    }
    private var confirmBlock: (VideoItem) -> Unit = {}
    fun onConfirm(block: (VideoItem) -> Unit) {
        this.confirmBlock = block
    }
}